.data

.globl X
.globl Y
X:	.word 232 225 241 242 210 231 125 173 290 286  65 275 165 150 200
Y:	.word 292 180 196 220 270 208 250 241 132  95 260 150 201 150 180
Y_end:
array_size = (Y_end - X) / 8

D:	.word 0 : array_size

# syscall constants
PRINT_INT = 1
PRINT_CHAR = 11

# spimbot constants
VELOCITY = 0xffff0010
BOT_X = 0xffff0020
BOT_Y = 0xffff0024

.text

.globl main
main:
	sub	$sp, $sp, 12
	sw	$ra, 8($sp)
	sw	$zero, VELOCITY	# stop the bot

	lw	$a0, BOT_X
	lw	$a1, BOT_Y
	la	$a2, X
	la	$a3, Y
	la	$t0, D
	sw	$t0, 0($sp)
	li	$t0, array_size
	sw	$t0, 4($sp)
	jal	iteratePath

whee:
	j	whee

	# never reached, but included for completeness
	lw	$ra, 8($sp)
	add	$sp, $sp, 12
	jr	$ra


# selectSmallest #######################################################
#
# arguments $a0: array of (i.e. pointer to) integers
#           $a1: size of array
#

selectSmallest:
	lw	$t0, 0($a0)		# min_array = numbers[0]
	li	$v0, 0			# min_location = 0
	li	$t1, 1			# i = 1

smallest_for:
	bge	$t1, $a1, smallest_swap	# !(i < array_size)
	mul	$t2, $t1, 4		# i * 4
	add	$t2, $a0, $t2		# &numbers[i]
	lw	$t2, 0($t2)		# numbers[i]
	bge	$t2, $t0, smallest_skip	# !(numbers[i] < min_array)
	move	$v0, $t1		# min_location = i
	move	$t0, $t2		# min_array = numbers[i]

smallest_skip:
	add	$t1, $t1, 1		# i++
	j	smallest_for

smallest_swap:
	lw	$t1, 0($a0)		# temp = numbers[0]
	sw	$t0, 0($a0)		# numbers[0] = min_array
	mul	$t2, $v0, 4		# min_location * 4
	add	$t2, $a0, $t2		# &numbers[min_location]
	sw	$t1, 0($t2)		# numbers[min_location] = temp
	jr	$ra			# return min_location (already in $v0)


# calculateDistance ####################################################
#
# arguments $a0:    x1 coordinate
#           $a1:    y1 coordinate
#           $a2:    array of x coordinates
#	    $a3:    array of y coordinates
#           0($sp): array of distances (to be modified)
#           4($sp): size of array(s) 

calculateDistance:
	lw	$t0, 0($sp)		# distances
	lw	$t1, 4($sp)		# array_size
	li	$t2, 0 			# i

distance_for:
	bge	$t2, $t1, distance_done	# !(i < array_size)
	mul	$t3, $t2, 4		# i * 4

	add	$t4, $a2, $t3		# &x_coords[i]
	lw	$t4, 0($t4)		# x_coords[i]
	sub	$t4, $a0, $t4		# x1 - x_coords[i]
	abs	$t4, $t4		# abs(x1 - x_coords[i])

	add	$t5, $a3, $t3		# &y_coords[i]
	lw	$t5, 0($t5)		# y_coords[i]
	sub	$t5, $a1, $t5		# y1 - y_coords[i]
	abs	$t5, $t5		# abs(y1 - y_coords[i])

	add	$t4, $t4, $t5		# abs(...) + abs(...)
	add	$t3, $t0, $t3		# &distances[i]
	sw	$t4, 0($t3)		# distances[i] = abs(...) + abs(...)
	add	$t2, $t2, 1		# i++
	j	distance_for

distance_done:
	jr	$ra


# calculatePath ########################################################
#
# arguments $a0:    spimbot x
#           $a1:    spimbot y
#           $a2:    array of x coordinates
#	          $a3:    array of y coordinates
#           0($sp): array of distances (to be modified)
#           4($sp): size of array(s) 

.globl calculatePath
calculatePath:
	# wait to test for synchronization with interrupt handler
	li	$t0, 14000
path_wait:
	sub	$t0, $t0, 1
	bge	$t0, 0, path_wait

	lw	$t0, 0($sp)		# distances
	lw	$t1, 4($sp)		# array_size

	sub	$sp, $sp, 20
	sw	$ra, 8($sp)
	sw	$a2, 12($sp)		# x_coords
	sw	$a3, 16($sp)		# y_coords

	sw	$t0, 0($sp)		# pass 5th argument on the stack
	sw	$t1, 4($sp)		# pass 6th argument on the stack
	jal	calculateDistance	# $a registers already hold correct values

	lw	$a0, 20($sp)		# distances
	lw	$a1, 24($sp)		# array_size
	jal	selectSmallest
	mul	$v0, $v0, 4		# min_index * 4

	lw	$a2, 12($sp)		# x_coords
	lw	$t0, 0($a2)		# temp = x_coords[0]
	add	$t1, $a2, $v0		# &x_coords[min_index]
	lw	$t2, 0($t1)		# x_coords[min_index]
	sw	$t2, 0($a2)		# x_coords[0] = x_coords[min_index]
	sw	$t0, 0($t1)		# x_coords[min_index] = temp

	lw	$a3, 16($sp)		# y_coords
	lw	$t0, 0($a3)		# temp = y_coords[0]
	add	$t1, $a3, $v0		# &y_coords[min_index]
	lw	$t2, 0($t1)		# y_coords[min_index]
	sw	$t2, 0($a3)		# y_coords[0] = y_coords[min_index]
	sw	$t0, 0($t1)		# y_coords[min_index] = temp

	lw	$a0, 0($a2)
	jal	print_int_and_space	# print closest x_coord of this iteration
	lw	$a0, 0($a3)
	jal	print_int_and_newline	# print closest y_coord of this iteration

	lw	$ra, 8($sp)
	add	$sp, $sp, 20
	jr	$ra



# print int and space ##################################################
#
# argument $a0: number to print

print_int_and_space:
	li	$v0, PRINT_INT	# load the syscall option for printing ints
	syscall			# print the number

	li	$a0, ' '	# print a blank space
	li	$v0, PRINT_CHAR	# load the syscall option for printing chars
	syscall			# print the char
	
	jr	$ra		# return to the calling procedure


# print int and new line ##################################################
#
# argument $a0: number to print

print_int_and_newline:
	li	$v0, PRINT_INT	# load the syscall option for printing ints
	syscall			# print the number

	li	$a0, '\n'	# print a new line character
	li	$v0, PRINT_CHAR	# load the syscall option for printing chars
	syscall			# print the char
	
	jr	$ra		# return to the calling procedure
